/****************************************************************************
 *  _____       ______  _____
 * |_   _|     |  ____|/ ____|
 *   | |  _ __ | |__  | (___    Institute of Embedded Systems
 *   | | | '_ \|  __|  \___ \   Zürcher Hochschule für Angewandte
 *  _| |_| | | | |____ ____) |  Wissenschaften
 * |_____|_| |_|______|_____/   8401 Winterthur, Switzerland
 *
 ****************************************************************************
 *
 * @version $Rev: 146 $
 * @author  $Author: bacr $
 * @date    $Date: 2013-10-02 17:56:25 +0200 (Mi, 02 Okt 2013) $
 *
 ***************************************************************************/

#ifndef __SPI_MASTER_H__
#define __SPI_MASTER_H__

#include <stdint.h>
#include <stdbool.h>

#include "object.h"

#include "hcpp/ptp2_task.h"
#include "spi_cmd.h"
#include "spi_master_driver.h"
#include "spi_frame.h"


// DEFINES
// macro to calculate the size of struct members
#define member_size(type, member) sizeof(((type *)0)->member)



#define SPI_MESSAGE_QUEUE_MAX_LEN   (5)
#define MAX_SPI_IN_QUEUES           (2)
#define SPI_LO_PRIO_IN_QUEUE        (0)
#define SPI_HI_PRIO_IN_QUEUE        (1)


// typedefs



typedef enum{
  spi_master_fsm_idle,
  spi_master_fsm_tx,
  spi_master_fsm_ack_req,
  max_spi_fsm
}spi_master_fsm_e;



typedef struct _spi_msg_queue{
    uint8_t           len;
    spi_frame_t       msgs[SPI_MESSAGE_QUEUE_MAX_LEN];
}spi_msg_queue;

//typedef bool    (*frame_enqueue)(spi_master_t *spi_master, spi_frame_t *message, uint8_t prio);

typedef struct  {
    object_t                    obj;
    spi_master_fsm_e            fsm;
    spi_msg_queue               queues[MAX_SPI_IN_QUEUES];
    ptp2_task_t                 task_timeout;
    //uint32_t                    timeout;
    spi_cmd_t                   current_cmd;
    int8_t                      current_queue;      // indicates the priority
                                                    // of the message currently
                                                    // being sent
    spi_driver_t                driver;
    spi_master_frame_builder    frame_builder;
}spi_master_t;

bool            spi_master_init(spi_master_t *spi_master);
bool            spi_master_add_message(spi_master_t *spi_master, spi_frame_t *message, uint8_t prio);
spi_frame_t*    spi_master_msg_get_next(spi_master_t *spi_master);
bool            spi_queue_ready(spi_master_t *spi_master, uint8_t prio);


#endif


